/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 map_rect.h

	$Header: /heroes4/map_rect.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( MAP_RECT_H_INCLUDED )
#define MAP_RECT_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "map_point.h"

//------------------------------------------------------------------------
// region on an isometric map
//------------------------------------------------------------------------
struct t_map_rect_2d
{
	t_map_point_2d top_left;
	t_map_point_2d bottom_right;

	// Constructors
	t_map_rect_2d();
	t_map_rect_2d( int top, int left, int bottom, int right );
	t_map_rect_2d( t_map_point_2d const & top_left, t_map_point_2d const & size );

	// Member functions
	int				bottom() const;
	int				height() const;
	int				left() const;
	int				right() const;
	int				width() const;
	int				top() const;
	void			merge( t_map_rect_2d const& right );

	t_map_point_2d top_right() const;
	t_map_point_2d bottom_left() const;

	t_map_point_2d size() const;

	// Operators
	t_map_rect_2d & operator+=( t_map_point_2d const & point );
	t_map_rect_2d & operator-=( t_map_point_2d const & point );
};

//------------------------------------------------------------------------
// inlines for t_map_rect_2d
//------------------------------------------------------------------------
inline t_map_rect_2d::t_map_rect_2d()
{
}

inline t_map_rect_2d::t_map_rect_2d(  int top, int left, int bottom, int right )
                    : top_left( top, left ), bottom_right( bottom, right )
{
}

inline t_map_rect_2d::t_map_rect_2d( t_map_point_2d const & new_top_left, 
									 t_map_point_2d const & size )
					: top_left( new_top_left ),
					  bottom_right( new_top_left.row + size.row,
					                new_top_left.column + size.column )
{
}

inline int t_map_rect_2d::bottom() const
{
	return bottom_right.row;
}

	// Member functions
inline 	int t_map_rect_2d::height() const
{
	return bottom_right.row - top_left.row;
}

inline int t_map_rect_2d::left() const
{
	return top_left.column;
}

inline int t_map_rect_2d::right() const
{
	return bottom_right.column;
}

inline 	int t_map_rect_2d::width() const
{
	return bottom_right.column - top_left.column;
}

inline int t_map_rect_2d::top() const
{
	return top_left.row;
}

inline 	t_map_point_2d t_map_rect_2d::top_right() const
{
	return t_map_point_2d( top_left.row, bottom_right.column );
}

inline 	t_map_point_2d t_map_rect_2d::bottom_left() const
{
	return t_map_point_2d( bottom_right.row, top_left.column );
}

inline 	t_map_point_2d t_map_rect_2d::size() const
{
	return bottom_right - top_left;
}

	// Operators
inline t_map_rect_2d & t_map_rect_2d::operator+=( t_map_point_2d const & point )
{
	top_left += point;
	bottom_right += point;
	return *this;
}

inline t_map_rect_2d & t_map_rect_2d::operator-=( t_map_point_2d const & point )
{
	top_left -= point;
	bottom_right -= point;
	return *this;
}

// return the rectangle enclosing both rectangles.
inline void t_map_rect_2d::merge( t_map_rect_2d const& right )
{
	if (top_left.column > right.top_left.column)
		top_left.column = right.top_left.column;
	if (top_left.row > right.top_left.row)
		top_left.row = right.top_left.row;
	if (bottom_right.column < right.bottom_right.column)
		bottom_right.column = right.bottom_right.column;
	if (bottom_right.row < right.bottom_right.row)
		bottom_right.row = right.bottom_right.row;
}

// return true if the two rectangles intersect
inline bool intersect( t_map_rect_2d const & left, t_map_rect_2d const & right )
{
	return		left.left() < right.right()
			&&	right.left() < left.right()
			&&	left.top() < right.bottom()
			&&	right.top() < left.bottom();
}

// return a rectangle containing the intersection of left and right
inline t_map_rect_2d intersection( t_map_rect_2d const & left, t_map_rect_2d const & right )
{
	return	t_map_rect_2d(
				left.top() > right.top() ? left.top() : right.top(),
				left.left() > right.left() ? left.left() : right.left(),
				left.bottom() < right.bottom() ? left.bottom() : right.bottom(),
				left.right() < right.right() ? left.right() : right.right() );
}

// return the rectangle enclosing both rectangles.
inline t_map_rect_2d get_extent( t_map_rect_2d const& left, t_map_rect_2d const& right )
{
	t_map_rect_2d result( left );

	result.merge( right );
	return result;
}



//------------------------------------------------------------------------
// Free functions
//------------------------------------------------------------------------
inline bool operator==( t_map_rect_2d const& left, t_map_rect_2d const& right )
{
	return    left.bottom() == right.bottom() 
		   && left.left() == right.left()
		   && left.right() == right.right()
		   && left.top() == right.top();

}

inline bool operator!=( t_map_rect_2d const& left, t_map_rect_2d const& right )
{
	return !( left == right );
}

//------------------------------------------------------------------------
// region on an isometric map
//------------------------------------------------------------------------
struct t_map_rect : public t_map_rect_2d
{
	int level;

	t_map_rect();
	t_map_rect( int top, int left, int bottom, int right, int level );
};

//------------------------------------------------------------------------
// inlines for t_map_rect
//------------------------------------------------------------------------
inline t_map_rect::t_map_rect()
{
}

inline t_map_rect::t_map_rect( int top, int left, int bottom, int right, int new_level )
          : t_map_rect_2d( top, left, bottom, right ), level( new_level )
{
}

#endif // MAP_RECT_H_INCLUDED

